<template>
  <div>
    <div
      class="relative flex-cc h-40 bg-slate-200 rounded-lg mb-2 bg-center bg-contain"
      :style="{backgroundImage:`url(${info?.img})`}"
    >
      <canvas ref="cvsRef" class="wh-full abso-lt"></canvas>
      <div class="font-bold text-white text-center text-shadow-lg z-10">
        <div class="text-xl">{{ info?.name }}</div>
        <div>{{ info?.author }}</div>
      </div>
      <div class="abso-lt z-10">
        <v-badge v-show="biliStatus==1" color="success" dot inline></v-badge>
        <v-badge v-show="biliStatus==0" color="grey" dot inline></v-badge>
        <v-badge v-show="biliStatus==-1" color="error" dot inline></v-badge>
      </div>
    </div>
    <div>
      <audio ref="audioRef" class="w-full h-10" controls></audio>
    </div>
  </div>
</template>

<script setup lang="ts">
import {ref,onMounted,watch} from 'vue';
import {gradient} from '@/utils/color';
import { getAudioBuffer } from '@/apis/kgApi';
import { useSettingsStore } from '@/stores/settings';
import { biliEmitter } from '@/utils/mitt';

const props = defineProps<{
  info?: SongInfo;
  user?: UserInfo
}>()
const emit = defineEmits<{
  (e: 'end'): void
}>()

const settingsStore=useSettingsStore();
const audioRef=ref<HTMLMediaElement>(),cvsRef=ref<HTMLCanvasElement>();
const url=ref(''),biliStatus=ref(0);

watch(() => settingsStore.volume,(val) =>{
  if(!audioRef.value) return;
  audioRef.value.volume=val;
})
watch(() => settingsStore.autoPlay,(val) =>{
  if(!audioRef.value) return;
  audioRef.value.autoplay=val;
})
const createAudioBytesFunc=(el:HTMLMediaElement) =>{
  const audCtx=new AudioContext();
  const source=audCtx.createMediaElementSource(el);
  const analyser = audCtx.createAnalyser();
  source.connect(analyser);
  analyser.connect(audCtx.destination);
  analyser.fftSize=512;
  const dataArr=new Uint8Array(analyser.frequencyBinCount);
  return () =>{
    analyser.getByteFrequencyData(dataArr);
    return dataArr;
  }
}
const drawWareCanvas=(el:HTMLCanvasElement,arr:Uint8Array) =>{
  if(!isPlaying) return;
  const { width, height } = el;
  const ctx=el.getContext('2d');
  ctx?.clearRect(0, 0, width, height);
  const len = arr.length /4;
  const barWidth = width / len;
  const colors=gradient('ff0000','00ff00',len);
  for (let i = 0; i < len; i++) {
    ctx!.fillStyle = `#${colors[i]}`;
    const data = arr[i];
    const barHeight = data / 255 * height;
    const x = i * barWidth;
    const y = height - barHeight;
    ctx?.fillRect(x, y, barWidth - 1 , barHeight);
  }
}
const createAudioUrl=() =>{
  const audioEl=<HTMLMediaElement>audioRef.value;
  const ms=new MediaSource();
  url.value=URL.createObjectURL(ms);
  ms.addEventListener('sourceopen',() =>{
  const buffer=ms.addSourceBuffer('audio/mpeg');
    getAudioBuffer(props.info?.src,buffer);
    buffer.addEventListener("updateend", () =>{
      ms.endOfStream();
      if(!audioEl.autoplay||!canPlay) return;
      audioEl.play();
    });
  })
}
const playSong=async () =>{
  const audioEl=<HTMLMediaElement>audioRef.value;
  const cvsEl=<HTMLCanvasElement>cvsRef.value;
  if(!audioEl) return;
  if(!props.info?.src) return;
  createAudioUrl();
  audioEl.autoplay=settingsStore.autoPlay;
  audioEl.volume=settingsStore.volume;
  audioEl.crossOrigin='anonymous';
  //audioEl.src=props.info?.src;
  audioEl.src=url.value;
  //audioEl.src='https://webfs.hw.kugou.com/202309041032/b2b0de1b63bf364300009e4efbfd555a/KGTX/CLTX001/5d2f025d6060026664d9d55e78a6cb5b.mp3'
  audioEl.loop=false;
  audioEl.oncanplay=() =>{
    //if(!canPlay) return;
    //audioEl.play();
  }
  audioEl.onplay=() =>{
    isPlaying=true;
    if(isInit) return;
    const getAudioBytes=createAudioBytesFunc(audioEl);
    const drawSongWare=() =>{
      const arr=getAudioBytes();
      drawWareCanvas(cvsEl,arr);
      requestAnimationFrame(drawSongWare);
    };
    drawSongWare();
    isInit=true;
  }
  audioEl.onpause=() =>{
    isPlaying=false;
  }
  audioEl.onended=() =>{
    URL.revokeObjectURL(url.value);
    url.value=""
    emit('end');
  }
}
let isInit=false,isPlaying=false,canPlay=false;

watch(() => props.info,(_val) =>{
  playSong();
})
onMounted(() =>{
  document.addEventListener('mousedown',() =>{
    if(canPlay) return;
    canPlay=true;
    playSong()
  })
  biliEmitter.on('bili:open',() =>{
    biliStatus.value=1
  })
  biliEmitter.on('bili:close',() =>{
    biliStatus.value=0
  })
  biliEmitter.on('bili:error',() =>{
    biliStatus.value=-1
  })
});
</script>

<style scoped>

</style>